#include "ctrl_equalizer.h"
#include <wx/dcgraph.h>

wxDEFINE_EVENT(myEVT_EQUALIZER, MyEventEqualizer);
wxDEFINE_EVENT(myEVT_EQUALIZER_FREQUENCY, MyEventEqualizer);
wxDEFINE_EVENT(myEVT_EQUALIZER_GAIN, MyEventEqualizer);
wxDEFINE_EVENT(myEVT_EQUALIZER_QFACTOR, MyEventEqualizer);
wxDEFINE_EVENT(myEVT_EQUALIZER_TYPE, MyEventEqualizer);

wxBEGIN_EVENT_TABLE(GraphicEqualizer, wxControl)
    EVT_PAINT  (GraphicEqualizer::OnPaint)
    EVT_SIZE  (GraphicEqualizer::OnSize)
    EVT_MOTION (GraphicEqualizer::OnMouseMove)
    EVT_LEFT_DOWN (GraphicEqualizer::OnMouseDown)
    EVT_LEFT_UP (GraphicEqualizer::OnMouseUp)
    EVT_MOUSEWHEEL(GraphicEqualizer::OnMouseWheel)
    EVT_LEFT_DCLICK(GraphicEqualizer::OnMouseLeftDClick)
wxEND_EVENT_TABLE()


GraphicEqualizer::GraphicEqualizer(wxWindow *parent, wxWindowID id, const wxString &label, const wxPoint &pos, const wxSize &size)
    : wxControl(parent, id, pos,size,wxBORDER_NONE)
{
    label_title = label;

    // SetBackgroundColour(wxColour(255, 0, 0)); // 设置背景色为红色
    // SetForegroundColour(*wxBLACK);
    SetBackgroundStyle(wxBG_STYLE_CUSTOM);
    sample_rate = 48000;
    freq_interval = 5;
    freq_start = 20;
    freq_end = sample_rate / 2;
    gain_max = 24;
    q_factor_min = 0.01;
    q_factor_max = 100;
    mouse_down = false;
    current_select_index = -1;
    ComputeCurveCoordX(freq_start,freq_end,freq_interval);
    filter_data_list.clear();

    //Bind方式比事件表要耗资源
    // Bind(wxEVT_PAINT, &GraphicEqualizer::OnPaint, this);
    // Bind(wxEVT_SIZE, &GraphicEqualizer::OnSize, this);
    // Bind(wxEVT_MOTION, &GraphicEqualizer::OnMouseMove, this);
    // Bind(wxEVT_LEFT_DOWN, &GraphicEqualizer::OnMouseDown, this);
    // Bind(wxEVT_LEFT_UP, &GraphicEqualizer::OnMouseUp, this);
    // Bind(wxEVT_MOUSEWHEEL, &GraphicEqualizer::OnMouseWheel, this);

    // AddFilter(Lowshelf,sample_rate,100,20,0.747);
    // AddFilter(Peak,sample_rate,200,10,0.747);
    // AddFilter(Peak,sample_rate,600,-10,0.747);
    // AddFilter(Peak,sample_rate,1000,15,0.747);
    // AddFilter(Peak,sample_rate,2000,-13,0.747);
    // AddFilter(Peak,sample_rate,5000,24,0.747);
    // AddFilter(Peak,sample_rate,8000,6,0.747);
    // AddFilter(Highshelf,sample_rate,16000,-10,0.747);
    equalizer_event.SetIndex(-1);
    equalizer_event.SetEventType(myEVT_EQUALIZER);
    // equalizer_event.SetId(GetId());
    equalizer_event.SetEventObject(this);
}

GraphicEqualizer::~GraphicEqualizer()
{
    for(int i=0; i<filter_data_list.size(); i++)
    {
        if(filter_data_list[i] != nullptr)
        {
            delete filter_data_list[i];
        }
    }
}

void GraphicEqualizer::OnSize(wxSizeEvent &event)
{
    Refresh();
    event.Skip();
}


void GraphicEqualizer::AddFilter(FilterType type, double frequency, double gain,double qfactor)
{
    EqualizerData *ed = new EqualizerData;

    ed->center_frequency = frequency;
    ed->gain = gain;
    ed->q_factor = qfactor;
    ed->type = type;
    FilterCoefficient coe;
    CalculationCoefficient(type,frequency,gain,qfactor,sample_rate,&coe);
    GetFrequencyResponseData(freq_start,freq_end,freq_interval,sample_rate,coe,ed->frequency_response_data);
    mutex.Lock();
    filter_data_list.push_back(ed);
    mutex.Unlock();
}

void GraphicEqualizer::SetSampleRate(double rate)
{
    sample_rate = rate;
}

void GraphicEqualizer::SetFilterType(int index,FilterType type)
{
    mutex.Lock();
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        filter_data_list[index]->type = type;
    }
    mutex.Unlock();
}

void GraphicEqualizer::SetFilterFrequency(int index, double frequency)
{
    mutex.Lock();
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        filter_data_list[index]->center_frequency = frequency;
    }
    mutex.Unlock();
}

void GraphicEqualizer::SetFilterGain(int index, double gain)
{
    mutex.Lock();
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        filter_data_list[index]->gain = gain;
    }
    mutex.Unlock();
}

void GraphicEqualizer::SetFilterQFactor(int index, double qfactor)
{
    mutex.Lock();
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        filter_data_list[index]->q_factor = qfactor;
    }
    mutex.Unlock();
}

double GraphicEqualizer::GetSampleRate(int index)
{
    return sample_rate;
}

FilterType GraphicEqualizer::GetFilterType(int index)
{
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        return filter_data_list[index]->type;
    }
    return FilterType::Peak;
}

double GraphicEqualizer::GetFilterGain(int index)
{
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        return filter_data_list[index]->gain;
    }
    return 0;
}

double GraphicEqualizer::GetFilterQFactor(int index)
{
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        return filter_data_list[index]->q_factor;
    }
    return 0;
}

double GraphicEqualizer::GetFilterFrequency(int index)
{
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        return filter_data_list[index]->center_frequency;
    }
    return 0;
}

void GraphicEqualizer::FilterUpdate(int index)
{
    if((index < filter_data_list.size()) && (index < EQUALIZER_MAX_FILTER))
    {
        FilterCoefficient coe;
        CalculationCoefficient(filter_data_list[index]->type, filter_data_list[index]->center_frequency, filter_data_list[index]->gain, filter_data_list[index]->q_factor, sample_rate,&coe);
        mutex.Lock();
        GetFrequencyResponseData(freq_start,freq_end,freq_interval,sample_rate,coe,filter_data_list[index]->frequency_response_data);
        mutex.Unlock();
        Refresh();
    }
}

void GraphicEqualizer::FilterUpdateAll(void)
{
    if((filter_data_list.size() > 0) && (filter_data_list.size() < EQUALIZER_MAX_FILTER))
    {
        FilterCoefficient coe;
        for(int index = 0; index < filter_data_list.size(); index++)
        {
            CalculationCoefficient(filter_data_list[index]->type, filter_data_list[index]->center_frequency, filter_data_list[index]->gain, filter_data_list[index]->q_factor, sample_rate,&coe);
            mutex.Lock();
            GetFrequencyResponseData(freq_start,freq_end,freq_interval,sample_rate,coe,filter_data_list[index]->frequency_response_data);
            mutex.Unlock();
        }
        Refresh();
    }
}

void GraphicEqualizer::ClearAllFilter(void)
{
    mutex.Lock();
    for(int index = 0; index < filter_data_list.size(); index++)
    {
        delete filter_data_list[index];
    }
    filter_data_list.clear();
    mutex.Unlock();
}

void GraphicEqualizer::OnPaint(wxPaintEvent &event)
{
    wxRect rect_panel(wxPoint(0, 0), GetClientSize());
    wxRect rect_curve(rect_panel.GetX()+left_margin,rect_panel.GetY()+top_margin,rect_panel.GetWidth()-right_margin-left_margin,rect_panel.GetHeight()-bottom_margin-top_margin);
    const int numPoints = coord_coef_x.size();
    int startX = rect_curve.GetX();
    int startY = rect_curve.GetY();
    int width = rect_curve.GetWidth();
    int height = rect_curve.GetHeight();
    int endX = startX;
    double heigh_half = height / 2;
    wxString txt_current;

    wxPaintDC dc(this);
    wxMemoryDC memDC;
    wxBitmap bitmap(GetClientSize());
    memDC.SelectObject(bitmap);

    memDC.SetBackground(wxBrush(wxColour(140, 140, 140)));
    memDC.Clear();

    memDC.SetPen(wxPen(wxColour(0, 0, 0),2));
    memDC.SetBrush(wxBrush(wxColour(128, 128, 128)));
    //memDC.DrawRoundedRectangle(rect_curve.GetX(), rect_curve.GetY(), rect_curve.GetWidth(), rect_curve.GetHeight(), 5);
    memDC.DrawRectangle(rect_curve.GetX(), rect_curve.GetY(), rect_curve.GetWidth(), rect_curve.GetHeight());

    wxGraphicsContext *gc = wxGraphicsContext::Create(memDC);
    if(gc)
    {
        gc->SetAntialiasMode(wxANTIALIAS_DEFAULT);
    }
    wxGCDC gcdc;
    gcdc.SetBackground(GetBackgroundColour());
    gcdc.SetGraphicsContext(gc);
    wxDC &wxdc = static_cast<wxDC&>(gcdc);

    mutex.Lock();
    //画每个点的频响线
    wxPoint *points = new wxPoint[numPoints+2];
    for(int n=0; n<filter_data_list.size() && n < EQUALIZER_MAX_FILTER; n++)
    {
        wxGraphicsPath path = gc->CreatePath();
        double *frd = &filter_data_list[n]->frequency_response_data[0];
        for(int i=0; i<numPoints; i++)
        {
            points[i+1].x = startX + width * coord_coef_x[i];
            points[i+1].y = startY + heigh_half - (frd[i] / gain_max) * heigh_half;
            // path.AddLineToPoint(startX + width * coord_coef_x[i],startY + heigh_half - (frd[i] / gain_max) * heigh_half);
        }
        points[0].x = points[1].x;
        points[0].y = startY + heigh_half;
        points[numPoints+1].x = startX+width;
        points[numPoints+1].y = startY + heigh_half;
        wxColour pen_colour(curve_color[n].GetRed(),curve_color[n].GetGreen(),curve_color[n].GetBlue(),20);
        if(current_select_index == n)
        {
            wxColor pc = wxColour(curve_color[n].GetRed(),curve_color[n].GetGreen(),curve_color[n].GetBlue(),150);
            wxdc.SetPen(wxPen(pc,2));
            wxdc.SetBrush(wxBrush(pc));
        }
        else
        {
            wxdc.SetPen(wxPen(pen_colour,2));
            wxdc.SetBrush(wxBrush(pen_colour));
        }
        wxdc.DrawSpline(numPoints+0, points+1);
        wxdc.DrawPolygon(numPoints+2, points,0,0,wxWINDING_RULE);
        // gc->StrokePath(path);

    }
    //画最终频响线
    {
        double *rec_curve = new double[numPoints];
        memset(rec_curve,0,numPoints*sizeof(double));
        for(int n=0; n<filter_data_list.size() && n < EQUALIZER_MAX_FILTER; n++)
        {
            double *frd = &filter_data_list[n]->frequency_response_data[0];
            for(int i=0; i<numPoints; i++)
            {
                rec_curve[i] += frd[i];
            }
        }
        for(int i=0; i<numPoints; i++)
        {
            points[i+0].x = startX + width * coord_coef_x[i];
            points[i+0].y = startY + heigh_half - (rec_curve[i] / gain_max) * heigh_half;
        }
        wxdc.SetPen(wxPen(wxColor(255,255,255),3));
        wxdc.DrawSpline(numPoints+0, points);
        delete[] rec_curve;
    }
    delete[] points;
    //画点
    double diff = hzLogDiff;
    double freq_log_start = ::log10(freq_start);
    for(int n=0; n<filter_data_list.size() && n < EQUALIZER_MAX_FILTER; n++)
    {
        int x = startX + width * ((::log10(filter_data_list[n]->center_frequency) - freq_log_start) / diff);
        int y = startY + heigh_half - (filter_data_list[n]->gain / gain_max) * heigh_half;
        wxdc.SetPen(wxPen(curve_color[n],2));
        wxdc.SetBrush(wxBrush(curve_color[n]));
        wxdc.DrawCircle(x,y,5);
    }
    //dB刻度
    int db_min = 0-gain_max;
    int db_max = gain_max;
    int db_interval = 4;
    int db_scale_line_length = 5;
    int db_scale_line_width = 2;
    wxdc.SetPen(wxPen(wxColour(0, 0, 0),db_scale_line_width));
    wxString label;
    wxSize labelSize;
    for (int i = db_max; i >= db_min; i -= db_interval)
    {
        int y = startY + heigh_half - i/gain_max * heigh_half;
        // y -= 1;
        wxdc.DrawLine(startX-db_scale_line_length, y, startX, y);
        label = wxString::Format(wxT("%d"), i);
        labelSize = wxdc.GetTextExtent(label);
        wxdc.DrawText(label, startX-db_scale_line_length-labelSize.GetWidth()*1.2, y-labelSize.GetHeight()/2);
    }
    //Hz刻度
    int hz_scale_line_length = 5;
    int hz_scale_line_width = 2;
    wxdc.SetPen(wxPen(wxColour(0, 0, 0),hz_scale_line_width));
    for (int i = 0; i < FREQUENCY_LAB_NUM; i++)
    {
        int x = startX + hz_lab_axis_coef[i] * width;
        wxdc.DrawLine(x, startY + height, x, startY + height + hz_scale_line_length);
        labelSize = wxdc.GetTextExtent(hz_lab_string[i]);
        wxdc.DrawText(hz_lab_string[i], x-(labelSize.GetWidth()/2), startY + height + hz_scale_line_length * 1.2);
    }
    if((current_select_index >= 0) && (current_select_index < filter_data_list.size()) && (current_select_index < EQUALIZER_MAX_FILTER))
    {
        // MyCommon mycommon;
        std::string str_freq = mDoubleToString(filter_data_list[current_select_index]->center_frequency);
        std::string str_gain = mDoubleToString(filter_data_list[current_select_index]->gain);
        std::string str_q = mDoubleToString(filter_data_list[current_select_index]->q_factor);
        std::string str_type = std::string(FilterTypeName[filter_data_list[current_select_index]->type]);

        // txt_current = wxString::Format(wxT("Type:%s,Frequency:%sHz,Gain:%s,Q:%s"),FilterTypeName[filter_data_list[current_select_index]->type],str_freq.begin(),str_gain.begin(),str_q.begin());
        txt_current = wxString(wxT("Type:") + str_type + wxT(",Frequency:") + str_freq + wxT("Hz,Gain:") + str_gain + wxT(",Q:") + str_q);
        memDC.SetPen(wxPen(wxColour(0, 0, 0),2));
        // memDC.SetTextForeground(curve_color[current_select_index]);
        // memDC.DrawText(txt_current,0,0);
        memDC.DrawLabel(txt_current, wxRect(rect_panel.GetWidth()/2, 5, 0, 0), wxALIGN_CENTER_HORIZONTAL);
    }
    mutex.Unlock();
    dc.Blit(0, 0, GetClientSize().GetWidth(), GetClientSize().GetHeight(), &memDC, 0, 0);
    event.Skip();
}
void GraphicEqualizer::OnMouseMove(wxMouseEvent &event)
{
    wxPoint point = event.GetPosition();
    if(mouse_down && (current_select_index >= 0) && (current_select_index < filter_data_list.size()) && (current_select_index < EQUALIZER_MAX_FILTER))
    {
        wxRect rect_panel(wxPoint(0, 0), GetClientSize());
        wxRect rect_curve(rect_panel.GetX()+left_margin,rect_panel.GetY()+top_margin,rect_panel.GetWidth()-right_margin-left_margin,rect_panel.GetHeight()-bottom_margin-top_margin);
        if(point.x < rect_curve.GetX())
        {
            point.x = rect_curve.GetX();
        }
        else if(point.x > (rect_curve.GetX() + rect_curve.GetWidth()))
        {
            point.x = rect_curve.GetX() + rect_curve.GetWidth();
        }
        if(point.y < rect_curve.GetY())
        {
            point.y = rect_curve.GetY();
        }
        else if(point.y > (rect_curve.GetY() + rect_curve.GetHeight()))
        {
            point.y = rect_curve.GetY() + rect_curve.GetHeight();
        }
        //if((point.x >= rect_curve.GetX()) && (point.x <= (rect_curve.GetX() + rect_curve.GetWidth())) && (point.y >= rect_curve.GetY()) && (point.y <= (rect_curve.GetY() + rect_curve.GetHeight())))
        {
            double x = point.x - rect_curve.GetX();
            double y = point.y - rect_curve.GetY();
            double w = rect_curve.GetWidth();
            double h = rect_curve.GetHeight();
            double db,freq;
            db = gain_max - ((y/h) * (gain_max * 2));
            if(db > gain_max)
            {
                db = gain_max;
            }
            else if(db < (0-gain_max))
            {
                db = 0 - gain_max;
            }
            double xr = x / w;
            freq = ::floorl(::pow(10,xr * hzLogDiff + ::log10(freq_start)));
            if(freq < freq_start)
            {
                freq = freq_start;
            }
            else if(freq > freq_end)
            {
                freq = freq_end;
            }
            filter_data_list[current_select_index]->center_frequency = freq;
            filter_data_list[current_select_index]->gain = db;
            FilterCoefficient coe;
            CalculationCoefficient(filter_data_list[current_select_index]->type, filter_data_list[current_select_index]->center_frequency, filter_data_list[current_select_index]->gain, filter_data_list[current_select_index]->q_factor, sample_rate,&coe);
            mutex.Lock();
            GetFrequencyResponseData(freq_start,freq_end,freq_interval,sample_rate,coe,filter_data_list[current_select_index]->frequency_response_data);
            mutex.Unlock();

            // equalizer_event.SetEventType(myEVT_EQUALIZER_FREQUENCY);
            equalizer_event.SetEventType(myEVT_EQUALIZER);
            equalizer_event.SetIndex(current_select_index);
            equalizer_event.SetQFactor(filter_data_list[current_select_index]->q_factor);
            equalizer_event.SetFrequency(filter_data_list[current_select_index]->center_frequency);
            equalizer_event.SetGain(filter_data_list[current_select_index]->gain);
            equalizer_event.SetType(filter_data_list[current_select_index]->type);
            ProcessWindowEvent(equalizer_event);
            Refresh();
        }
    }
    event.Skip();
}

void GraphicEqualizer::OnMouseDown(wxMouseEvent &event)
{
    mouse_down = true;
    int ret = GetMouseClickArea(event);
    if(ret >= 0)
    {
        current_select_index = ret;
        // equalizer_event.SetEventType(myEVT_EQUALIZER);
        equalizer_event.SetIndex(current_select_index);
        // equalizer_event.SetQFactor(filter_data_list[current_select_index]->q_factor);
        // equalizer_event.SetFrequency(filter_data_list[current_select_index]->center_frequency);
        // equalizer_event.SetGain(filter_data_list[current_select_index]->gain);
        // equalizer_event.SetType(filter_data_list[current_select_index]->type);
        // ProcessWindowEvent(equalizer_event);
        Refresh();
    }
    else
    {
        if(current_select_index >= 0)
        {
            current_select_index = -1;
            Refresh();
        }
    }

    event.Skip();
}

void GraphicEqualizer::OnMouseUp(wxMouseEvent &event)
{
    mouse_down = false;
    event.Skip();
}

void GraphicEqualizer::OnMouseWheel(wxMouseEvent &event)
{
    if((current_select_index >= 0) && (current_select_index < filter_data_list.size()) && (current_select_index < EQUALIZER_MAX_FILTER))
    {
        double rota = event.GetWheelRotation();
        double delta = event.GetWheelDelta();
        double wheel = (rota / delta) * 0.01;
        double q = filter_data_list[current_select_index]->q_factor;
        q -= wheel;
        if(q > q_factor_max)
        {
            q = q_factor_max;
        }
        else if(q < q_factor_min)
        {
            q = q_factor_min;
        }
        filter_data_list[current_select_index]->q_factor = q;
        FilterCoefficient coe;
        CalculationCoefficient(filter_data_list[current_select_index]->type, filter_data_list[current_select_index]->center_frequency, filter_data_list[current_select_index]->gain, filter_data_list[current_select_index]->q_factor, sample_rate,&coe);
        mutex.Lock();
        GetFrequencyResponseData(freq_start,freq_end,freq_interval,sample_rate,coe,filter_data_list[current_select_index]->frequency_response_data);
        mutex.Unlock();
        Refresh();

        // equalizer_event.SetEventType(myEVT_EQUALIZER_QFACTOR);
        equalizer_event.SetEventType(myEVT_EQUALIZER);
        equalizer_event.SetIndex(current_select_index);
        equalizer_event.SetQFactor(filter_data_list[current_select_index]->q_factor);
        equalizer_event.SetFrequency(filter_data_list[current_select_index]->center_frequency);
        equalizer_event.SetGain(filter_data_list[current_select_index]->gain);
        equalizer_event.SetType(filter_data_list[current_select_index]->type);
        ProcessWindowEvent(equalizer_event);
    }
    event.Skip();
}

void GraphicEqualizer::OnMouseLeftDClick(wxMouseEvent &event)
{
    mouse_down = false;
    int ret = GetMouseClickArea(event);
    if(ret >= 0)
    {
        current_select_index = ret;
        Refresh();
        wxString title(wxString::Format("Filter %d",current_select_index+1));
        FilterParameterDialog filterDialog(wxID_ANY,this,title,filter_data_list[current_select_index]->type,filter_data_list[current_select_index]->center_frequency,filter_data_list[current_select_index]->gain,filter_data_list[current_select_index]->q_factor);
        int ret = filterDialog.ShowModal();
        if(ret == wxID_OK)
        {
            // FilterType type = filterDialog.GetType();
            // double frequency = filterDialog.GetFrequency();
            // double gain = filterDialog.GetGain();
            // double q_factor = filterDialog.GetQFactor();
            filter_data_list[current_select_index]->type = filterDialog.GetType();
            filter_data_list[current_select_index]->center_frequency = filterDialog.GetFrequency();
            filter_data_list[current_select_index]->gain = filterDialog.GetGain();
            filter_data_list[current_select_index]->q_factor = filterDialog.GetQFactor();
            FilterCoefficient coe;
            CalculationCoefficient(filter_data_list[current_select_index]->type, filter_data_list[current_select_index]->center_frequency, filter_data_list[current_select_index]->gain, filter_data_list[current_select_index]->q_factor, sample_rate,&coe);
            mutex.Lock();
            GetFrequencyResponseData(freq_start,freq_end,freq_interval,sample_rate,coe,filter_data_list[current_select_index]->frequency_response_data);
            mutex.Unlock();
            Refresh();
            equalizer_event.SetEventType(myEVT_EQUALIZER);
            equalizer_event.SetIndex(current_select_index);
            equalizer_event.SetQFactor(filter_data_list[current_select_index]->q_factor);
            equalizer_event.SetFrequency(filter_data_list[current_select_index]->center_frequency);
            equalizer_event.SetGain(filter_data_list[current_select_index]->gain);
            equalizer_event.SetType(filter_data_list[current_select_index]->type);
            ProcessWindowEvent(equalizer_event);
        }
    }
    else
    {
        if(current_select_index >= 0)
        {
            current_select_index = -1;
            Refresh();
        }
    }
    event.Skip();
}


void GraphicEqualizer::ComputeCurveCoordX(double start_freq, double end_freq, double freq_step)
{
    double f;
    double freq_log_start = ::log10(freq_start);
    double freq_log_end = ::log10(freq_end);
    hzLogDiff = ::log10(end_freq) - freq_log_start;
    coord_coef_x.clear();
    for(f=start_freq; f<=end_freq; f+=freq_step)
    {
        coord_coef_x.push_back((::log10(f) - freq_log_start) / hzLogDiff);
    }
    if(f != end_freq)
    {
        coord_coef_x.push_back((freq_log_end - freq_log_start) / hzLogDiff);
    }
    for (int i = 0; i < FREQUENCY_LAB_NUM; i++)
    {
        hz_lab_axis_coef[i] = (::log10(hz_lab[i]) - freq_log_start) / hzLogDiff;
    }
}

void GraphicEqualizer::GetFrequencyResponseData(double start_freq, double end_freq,double freq_step,double sampleRate,
                                           FilterCoefficient &coefficient,std::vector<double> &fq_data)
{
    const double PI = 3.1415926;
    double a1,a2,b0,b1,b2;
    double sf,ef;
    double phi;
    double r;
    double g;
    double dB;
    a1 = coefficient.a1;
    a2 = coefficient.a2;
    b0 = coefficient.b0;
    b1 = coefficient.b1;
    b2 = coefficient.b2;
    sf = start_freq;
    ef = end_freq;
    fq_data.clear();
    while(sf <= ef)
    {
        phi = ::pow((::sin(2.0 * PI * sf / (2.0 * sampleRate))), 2.0);
        r = (::pow(b0 + b1 + b2, 2.0) - 4.0 * (b0 * b1 + 4.0 * b0 * b2 + b1 * b2) * phi + 16.0 * b0 * b2 * phi * phi) / (::pow(1.0 + a1 + a2, 2.0) - 4.0 * (a1 + 4.0 * a2 + a1 * a2) * phi + 16.0 * a2 * phi * phi);
        if(r < 0) {
            r = 0;
        }
        g = ::sqrt(r);
        dB = 20 * ::log10(g == 0 ? 1 : g);
        fq_data.push_back(dB);
        sf += freq_step;
    }
    if(sf != ef)
    {
        sf = ef;
        phi = ::pow((::sin(2.0 * PI * sf / (2.0 * sampleRate))), 2.0);
        r = (::pow(b0 + b1 + b2, 2.0) - 4.0 * (b0 * b1 + 4.0 * b0 * b2 + b1 * b2) * phi + 16.0 * b0 * b2 * phi * phi) / (::pow(1.0 + a1 + a2, 2.0) - 4.0 * (a1 + 4.0 * a2 + a1 * a2) * phi + 16.0 * a2 * phi * phi);
        if(r < 0) {
            r = 0;
        }
        g = ::sqrt(r);
        dB = 20 * ::log10(g == 0 ? 1 : g);
        fq_data.push_back(dB);
    }
}

int GraphicEqualizer::GetMouseClickArea(wxMouseEvent &event)
{
    wxPoint point = event.GetPosition();
    wxRect rect_panel(wxPoint(0, 0), GetClientSize());
    wxRect rect_curve(rect_panel.GetX()+left_margin,rect_panel.GetY()+top_margin,rect_panel.GetWidth()-right_margin-left_margin,rect_panel.GetHeight()-bottom_margin-top_margin);
    if((point.x >= rect_curve.GetX()) && (point.x <= (rect_curve.GetX() + rect_curve.GetWidth())) && (point.y >= rect_curve.GetY()) && (point.y <= (rect_curve.GetY() + rect_curve.GetHeight())))
    {
        double x = point.x - rect_curve.GetX();
        double y = point.y - rect_curve.GetY();
        double w = rect_curve.GetWidth();
        double h = rect_curve.GetHeight();
        //获取全部点的坐标
        double diff = hzLogDiff;
        double freq_log_start = ::log10(freq_start);
        for(int n=0; n<filter_data_list.size() && n < EQUALIZER_MAX_FILTER; n++)
        {
            int x0 = w * ((::log10(filter_data_list[n]->center_frequency) - freq_log_start) / diff);
            int y0 = h/2 - (filter_data_list[n]->gain / gain_max) * (h/2);
            int x1 = x0 - 6;
            int y1 = y0 - 6;
            int x2 = x0 + 6;
            int y2 = y0 + 6;
            if((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2))
            {
                return n;
            }
        }
    }
    return -1;
}
